package whisper.service.auth.shiro.realm.jwt;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import whisper.common.exception.authorization.AccountExpiredException;
import whisper.common.exception.authorization.AuthenticationException;
import whisper.common.exception.authorization.DisabledException;
import whisper.common.exception.authorization.LockedException;
import whisper.common.support.response.WebResponseCode;
import whisper.common.utils.JWTUtils;
import whisper.service.auth.shiro.realm.AbstractRealm;
import whisper.service.auth.shiro.token.JWTToken;
import whisper.support.user.domain.User;

import java.util.Set;


/**
 * Created by JT on 2018/5/28
 */
public abstract class JWTRealm extends AbstractRealm {

    /**
     * 支持令牌方式  Token
     * @param token
     * @return
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    /**
     * 对用户授权
     * @param principal
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        String token = principal.toString();
        String username = JWTUtils.getUsername(token);
        Set<String> roles = findRoles(username);
        Set<String> permissions = findPermissions(username);

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRoles(roles);
        simpleAuthorizationInfo.addStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }

    /**
     * 登录调用 ,验证JWT是否正确
     * @param token
     * @return
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
        String username = JWTUtils.getUsername(token.getPrincipal().toString());

        if (StringUtils.isBlank(username))
            throw new AuthenticationException(WebResponseCode.CODE_ERROR,  WebResponseCode.MESSAGE_ERROR_TOKEN);

        User user = this.findUser(username);

        if (!JWTUtils.verify(token.getPrincipal().toString(), user.getUsername(), user.getPassword()))
            throw new AuthenticationException(WebResponseCode.CODE_ERROR, WebResponseCode.MESSAGE_ERROR_TOKEN);
        if (user.getIsAvailable() == 0)
            throw new DisabledException(WebResponseCode.CODE_ERROR, WebResponseCode.MESSAGE_ERROR_USER_IS_AVAILABLE);
        if (user.getIsLock() == 0)
            throw new LockedException(WebResponseCode.CODE_ERROR, WebResponseCode.MESSAGE_ERROR_USER_IS_LOCK);
        if (user.getIsOverdue() == 0)
            throw new AccountExpiredException(WebResponseCode.CODE_ERROR, WebResponseCode.MESSAGE_ERROR_USER_IS_EXPIRED);
        return new SimpleAuthenticationInfo(token.getPrincipal(), token.getPrincipal(), "ManagerRealm");
    }


    protected abstract User findUser(String username);

    protected abstract Set<String> findRoles(String username);

    protected abstract Set<String> findPermissions(String username);


}
